import { MsgLoadingClear, Msg } from '@C/Msg'
import { clearToken, getToken, refreshRequest, setRefreshToken, setToken } from '@U/Auth'
import { getReq, postReq, getFileReq, Router, storeState } from '@U/common'
import type { IFunc, IObj } from '@/interface'

export default function request(options: any) {
    options.url = `${/^http/.test(options.url) ? '' : import.meta.env.VITE_APP_BASE_API}${options?.url || ''}`
    options.timeout = 30000
    if (getToken()) {
        options.header.Authorization = `${getToken()}`
    }
    const whiteCodeList = [200, 100, 203, 212] // 212状态用来针对msg文字特别长，uni.showToast显示不全的情况
    return new Promise((resolve, reject) => {
        options.success = async (res: IObj) => {
            console.log('服务端环境：', res.header['X-Server-Env'])
            const code = res.statusCode
            if (code === 200 && options.responseType && options.responseType === 'arraybuffer') {
                getFileData(res.data)
                resolve(res.data)
            } else if (code === 200 && whiteCodeList.indexOf(res.data.code) !== -1) {
                if (res.data.code === 100 || res.data.code === 203) MsgLoadingClear({ msg: res.data.msg, duration: 3000 })
                resolve(res.data)
            } else if (code === 200 && whiteCodeList.indexOf(res.data.code) === -1) {
                MsgLoadingClear({ msg: res.data.msg })
                reject(res)
                if (res.data.code === 401) {
                    clearToken()
                    MsgLoadingClear({ icon: 'error', msg: '请重新登录' })
                    setTimeout(() => Router.reLaunch('login'), 1500)
                }
            } else if (code === 401) {
                const _refresh = await refreshToken(options)
                console.log('_refresh', _refresh)
                // if (!_refresh) {
                //     clearToken()
                //     MsgLoadingClear({ icon: 'error', msg: '请重新登录2' })
                //     setTimeout(() => Router.reLaunch('login'), 1500)
                // } else {
                    MsgLoadingClear()
                    resolve(_refresh)
                // }
            } else {
                MsgLoadingClear({ msg: res.data.msg })
                reject(res)
            }
        }
        options.fail = (err: IObj) => {
            MsgLoadingClear({ msg: '服务器错误' })
            reject(err)
        }
        uni.request(options)
    })
}

// 小程序 - 接收文件流并打开
function getFileData(data: any) {
    const filaname = storeState.fileStreamName
    const fs = uni.getFileSystemManager()
    fs.removeSavedFile({
        filePath: `${uni.env.USER_DATA_PATH}/${filaname}.doc`,
        complete: (innerRes) => {
            console.log('文件删除信息', innerRes)
            fs.writeFile({
                filePath: `${uni.env.USER_DATA_PATH}/${filaname}.doc`,
                data,
                encoding: 'binary',
                success: (e: any) => {
                    uni.openDocument({
                        filePath: `${uni.env.USER_DATA_PATH}/${filaname}.doc`,
                        fileType: 'doc',
                        showMenu: true,
                        success: (innerE: any) => {
                            console.log('打开文件', innerE)
                        },
                        fail: (innerErr: any) => {
                            console.log('innerErr', innerErr)
                        },
                    })
                },
                fail: (err: any) => {
                    Msg({ msg: err.errMsg || '文件写入失败' })
                },
            })
        },
    })
}
// 重新获取token并请求
export async function refreshToken(options?: IObj) {
    const { code: refreshCode, data: refreshData } = await refreshRequest().finally(() => {})
    if (refreshCode === 200) {
        const { token_type, access_token, refresh_token } = refreshData
        const token = `${ token_type } ${ access_token }`
        setToken(token)
        setRefreshToken(refresh_token)
        if (options) {
            // 不要使用return直接返回res!!!
            let res
            if (options.responseType && options.responseType === 'arraybuffer') res = await getFileReq(options.url, options.data)
            else res = await ({ GET: getReq, POST: postReq }[options.method as string] as IFunc)(options.url, options.data, options.header['content-type'])
            return res
        }
    }
    return false
}
